#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project : aimix
@File    : tools.py
@IDE     : PyCharm
@Author  : admin
@Date    : 2025/4/3 11:53
"""
import os
import sys
import time
import functools
import platform
import requests
import traceback
from fontTools.ttLib import TTFont
from concurrent.futures import ThreadPoolExecutor, as_completed


from log import log


def get_ffmpeg_path():
    """
    获取ffmpeg.exe的路径
    @return:
    """
    system_name = platform.system()
    if system_name == "Windows":
        if getattr(sys, 'frozen', False):
            return os.path.join(sys._MEIPASS, 'ffmpeg', 'bin')
        else:
            return os.path.join(os.getcwd(), 'ffmpeg', 'bin')
    else:
        raise OSError("不支持的操作系统")


def resource_path(relative_path):
    """ 动态获取资源绝对路径，兼容开发环境和打包环境 """
    if hasattr(sys, '_MEIPASS'):
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.normpath(os.path.join(base_path, relative_path))


def format_timestamp(seconds: float) -> str:
    """将秒转换成 SRT 格式时间戳"""
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    secs = int(seconds % 60)
    millis = int((seconds - int(seconds)) * 1000)
    return f"{hours:02}:{minutes:02}:{secs:02},{millis:03}"


def list_windows_fonts(font_dir: str = r"C:\Windows\Fonts"):
    fonts = {}

    # 定义常见的字体样式映射
    style_mapping = {
        'bd': 'Bold',
        'bi': 'Bold Italic',
        'i': 'Italic',
        'r': 'Regular',
        '': 'Regular'  # 默认没有样式时为 Regular
    }

    for filename in os.listdir(font_dir):
        if filename.lower().endswith(('.ttf', '.ttc', '.otf')):
            font_path = os.path.join(font_dir, filename)
            try:
                font = TTFont(font_path, fontNumber=0)
                family_name = ""
                style_name = ""

                # 获取字体的Family Name
                for record in font['name'].names:
                    if record.nameID == 1:  # Font family name
                        try:
                            family_name = record.string.decode(record.getEncoding())
                        except:
                            family_name = record.string.decode('utf-8', errors='ignore')
                        break

                # 提取字体样式（通过文件名中的一些关键词）
                base_name = filename.lower().replace(' ', '')  # 去除空格，并转换为小写
                for key, style in style_mapping.items():
                    if key in base_name:
                        style_name = style
                        break
                else:
                    style_name = style_mapping['']  # 如果没有找到样式，则默认 Regular

                # 合并字体名称（Family + Style）
                full_font_name = f"{family_name} {style_name}"

                # 将字体添加到字典中
                if family_name not in fonts:
                    fonts[family_name] = []
                fonts[family_name].append({
                    "file_name": filename,
                    "file_path": font_path,
                    "font_name": full_font_name
                })
            except Exception as e:
                # 跳过无法解析的字体文件
                continue
    return fonts


def parallel_run(func, args_list, max_workers=5):
    """并行运行函数"""
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = []
        result = []

        for args in args_list:
            if not isinstance(args, tuple) and not isinstance(args, list):
                args = (args,)

            futures.append(executor.submit(func, *args))
        for future in as_completed(futures):
            try:
                result.append(future.result())
            except Exception as e:
                log.error(f"函数 {func.__name__} 运行出错: {e}")
    return result


def retry(
    exceptions=Exception,  # 指定需要重试的异常类型，默认为所有异常
    tries=3,  # 重试次数，默认为 3 次
    delay=0,  # 每次重试之间的延迟时间（秒），默认为 0
    backoff=1,  # 延迟时间的倍数，用于指数退避，默认为 1（不退避）
    callback=None
):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            nonlocal delay  # 使用 nonlocal 修饰符，以便在嵌套函数中修改外部变量
            _tries, _delay = tries, delay  # 初始化重试次数和延迟时间
            last_exception = None  # 用于存储最后一次异常
            exception_content = ""  # 用于存储异常内容
            while _tries > 0:  # 当重试次数大于 1 时继续重试
                try:
                    return func(*args, **kwargs)  # 尝试执行被装饰的函数
                except exceptions as e:  # 捕获指定的异常
                    last_exception = e  # 保存异常
                    exception_content = traceback.format_exc()
                    time.sleep(_delay)  # 等待延迟时间
                    _tries -= 1  # 减少重试次数
                    _delay *= backoff  # 更新延迟时间（指数退避）

            if last_exception:  # 如果有异常
                print(exception_content)  # 打印异常日志
                if callback:  # 如果有失败的回调函数
                    callback(last_exception, *args, **kwargs)  # 调用失败的回调函数
                raise last_exception  # 返回错误信息
        return wrapper
    return decorator


@retry(tries=5, delay=1, backoff=1)
def request(url, method='GET', *args, **kwargs):
    """
    封装 requests 库，增加重试机制
    :param url: 请求地址
    :param method: 请求方法
    :param args: requests 库的其他参数
    :param kwargs: requests 库的其他参数
    :return: requests 库的响应对象
    """
    response = requests.request(method, url, *args, **kwargs)
    response.raise_for_status()
    return response
